package cn.edu.ctgu.ch1.measure;

import cn.edu.ctgu.ch1.WordsService;
import cn.edu.ctgu.ch1.config.WordConfig;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileNotFoundException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.util.Scanner;
import java.util.function.IntSupplier;

/**
 * @author tiger54910
 * @create 2025/1/31 17:04
 */
@Service("measuredDefaultWordsService")
public class MeasuredDefaultWordsService implements WordsService {
  private static final int MULTIPLY_FACTOR = 100;

  private static final IntSupplier DEFAULT_INDEX_PROVIDER =
      MeasuredDefaultWordsService::getIndexForToday;

  private Path filePath;

  private IntSupplier indexProvider;
  private final WordConfig wordConfig;
  private final MeterRegistry meterRegistry;

  @Autowired
  public MeasuredDefaultWordsService(WordConfig config,MeterRegistry meterRegistry) {
    this(config, meterRegistry, DEFAULT_INDEX_PROVIDER);
  }
  public MeasuredDefaultWordsService(WordConfig config,MeterRegistry meterRegistry,IntSupplier indexProvider) {
    this.wordConfig = config;
    this.meterRegistry = meterRegistry;
    this.indexProvider = indexProvider;
    this.filePath = getPath(wordConfig.getDictionary());
  }


  @Override
  public String getWordOfTheDay() {
    int index = indexProvider.getAsInt();
    try (Scanner scanner = new Scanner(filePath.toFile())) {
      int i = 0;
      while (scanner.hasNextLine()) {
        String line = scanner.nextLine();
        if (index == i) {
          return line;
        }
        i++;
      }
    } catch (FileNotFoundException e) {
      throw new RuntimeException("Problem in getWordOfTheDay for index: " + filePath, e);
    }

    return "No word today.";
  }

  @Override
  public boolean wordExists(String word) {
    Timer loadFile = Timer.builder("loadFile").description("加载词典").register(meterRegistry);
    try {
      Scanner scanner =
          loadFile.record(
              () -> {
                try {
                  return new Scanner(filePath.toFile());
                } catch (FileNotFoundException e) {
                  throw new RuntimeException(e);
                }
              });
      // scan if more costly, how to optimize it?
      Timer scan = Timer.builder("scan").description("遍历词典查找单词").register(meterRegistry);
      return scan.record(
          () -> {
            while (scanner.hasNextLine()) {
              String line = scanner.nextLine();
              if (word.equals(line)) {
                return true;
              }
            }
            return false;
          });
    } catch (Exception e) {
      throw new RuntimeException("Problem in wordExists for word: " + word, e);
    }
  }

  static int getIndexForToday() {
    LocalDate now = LocalDate.now();
    return now.getYear() + now.getDayOfYear() * MULTIPLY_FACTOR;
  }

  private Path getPath(String file) {
    return Paths.get(new File(file).toURI());
  }
}
